#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
火电厂冷端优化系统 - 模拟数据运行入口
用于在没有InfluxDB连接的情况下，使用模拟数据运行整个优化系统
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import logging
import os
import time
from datetime import datetime, timedelta
from opt_alg.bi_mp_pro2 import parallel_optimize
from opt_alg.param_ident2 import share_data

# 设置matplotlib中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Times New Roman']
plt.rcParams['axes.unicode_minus'] = False

class MockDataGenerator:
    """模拟数据生成器，用于替代InfluxDB数据源"""
    
    def __init__(self):
        # 基于真实运行数据的典型值范围
        self.data_ranges = {
            '机组负荷': (300, 500),      # MW
            '主汽流量': (350, 600),      # t/h
            '主汽温度': (530, 550),      # °C
            '主汽压力': (14, 17),        # MPa
            '再热蒸汽压力': (2.0, 3.0),  # MPa
            '再热蒸汽温度': (510, 530),  # °C
            '凝结水温度': (45, 55),      # °C
            '凝结水流量': (280, 350),    # t/h
            '主给水流量': (380, 450),    # t/h
            '环境温度': (15, 35),        # °C
            '风机转速': (40, 80),        # rpm
            '背压': (4, 8),              # kPa
            '风机台数': (50, 60)         # 台
        }
        
        # 历史数据缓存
        self.history_data = []
        self.current_time = datetime.now()
        
    def generate_single_data_point(self, base_load=None):
        """生成单个数据点"""
        if base_load is None:
            base_load = np.random.uniform(350, 450)
        
        # 基于负荷生成相关参数
        load_factor = (base_load - 300) / 200  # 归一化到0-1
        
        # 生成时间戳
        timestamp = self.current_time
        
        # 生成24维数据数组（基于代码中的input_points分析）
        data = np.zeros(24)
        
        # 时间戳（转换为数值）
        data[0] = timestamp.timestamp()
        
        # 机组负荷 (MW)
        data[1] = base_load + np.random.normal(0, 5)
        
        # 主汽流量 (t/h) - 与负荷相关
        data[2] = base_load * 1.1 + np.random.normal(0, 10)
        
        # 主汽温度 (°C)
        data[3] = 540 + np.random.normal(0, 2)
        
        # 主汽压力 (MPa)
        data[4] = 15.5 + np.random.normal(0, 0.5)
        
        # 再热蒸汽压力 (MPa)
        data[5] = 2.5 + np.random.normal(0, 0.1)
        
        # 再热蒸汽温度 (°C)
        data[6] = 520 + np.random.normal(0, 3)
        
        # 凝结水温度 (°C)
        data[7] = 50 + np.random.normal(0, 2)
        
        # 凝结水流量 (t/h)
        data[8] = 320 + np.random.normal(0, 15)
        
        # 主给水流量 (t/h)
        data[9] = base_load * 1.05 + np.random.normal(0, 10)
        
        # 主给水温度 (°C)
        data[10] = 240 + np.random.normal(0, 5)
        
        # 凝结水流量 (t/h) - 重复项，保持一致性
        data[11] = data[8]
        
        # 凝结水泵出口母管温度 (°C)
        data[12] = data[7] + np.random.normal(0, 1)
        
        # 风机转速 (rpm)
        data[13] = 60 + np.random.normal(0, 5)
        
        # 风机台数
        data[14] = 56
        
        # 背压 (kPa)
        data[15] = 6 + np.random.normal(0, 0.5)
        
        # 风机台数 (重复)
        data[16] = 56
        
        # 背压 (kPa) - 重复项
        data[17] = data[15]
        
        # 环境温度 (°C)
        data[18] = 25 + np.random.normal(0, 3)
        
        # 环境温度 (°C) - 重复项
        data[19] = data[18]
        
        # 抽汽压力相关参数 (基于负荷变化)
        data[20] = 6.9 + load_factor * 0.5 + np.random.normal(0, 0.1)  # 第一级抽汽压力
        data[21] = 4.1 + load_factor * 0.3 + np.random.normal(0, 0.1)  # 第二级抽汽压力
        data[22] = 2.1 + load_factor * 0.2 + np.random.normal(0, 0.05) # 第三级抽汽压力
        data[23] = 0.9 + load_factor * 0.1 + np.random.normal(0, 0.02) # 第四级抽汽压力
        
        return timestamp, data
    
    def generate_history_data(self, n_points=50, base_load=None):
        """生成历史数据序列"""
        history_data = []
        
        for i in range(n_points):
            # 随时间略微变化负荷
            if base_load is None:
                current_load = 400 + np.random.normal(0, 20)
            else:
                current_load = base_load + np.random.normal(0, 10)
            
            timestamp, data = self.generate_single_data_point(current_load)
            history_data.append([timestamp] + list(data))
            
            # 更新时间
            self.current_time += timedelta(minutes=5)
        
        return np.array(history_data)
    
    def get_latest_data(self):
        """获取最新数据点"""
        timestamp, data = self.generate_single_data_point()
        return timestamp, data.reshape(1, -1)
    
    def get_history_data(self, n=50):
        """获取历史数据"""
        return self.generate_history_data(n)

def setup_logger():
    """设置日志"""
    logger = logging.getLogger("simulation_runner")
    logger.setLevel(logging.INFO)
    
    # 创建控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    
    # 创建格式器
    formatter = logging.Formatter(
        '[%(asctime)s-%(name)s] (%(filename)s %(lineno)d): %(levelname)s %(message)s',
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    console_handler.setFormatter(formatter)
    
    # 添加处理器到logger
    logger.addHandler(console_handler)
    
    return logger

def run_single_optimization(data_generator, logger, load_scenario="normal"):
    """运行单次优化"""
    logger.info(f"开始运行 {load_scenario} 负荷场景的背压优化...")
    
    # 生成模拟数据
    if load_scenario == "high":
        base_load = 450
    elif load_scenario == "low":
        base_load = 350
    else:
        base_load = 400
    
    # 生成历史数据
    history_data = data_generator.generate_history_data(n_points=50, base_load=base_load)
    
    logger.info(f"生成历史数据: {len(history_data)} 个数据点")
    logger.info(f"当前负荷: {base_load:.1f} MW")
    
    # 运行优化算法
    try:
        # 获取模型参数
        ita_current, kc_current, sim_steps = share_data()
        logger.info(f"使用模型参数: 汽轮机效率={ita_current:.3f}, 凝汽器系数={kc_current:.3f}")
        
        # 运行并行优化
        matrix_best, trace_list = parallel_optimize(
            data=history_data,
            simtime=25,
            sample_time=5,
            h=0.1,
            tolerance=0.0005,
            precision=6,
            logger=logger
        )
        
        # 解析结果
        optimal_fan_speed = matrix_best[0, 0]  # 最优风机转速
        optimal_backpressure = matrix_best[0, 1]  # 最优背压
        optimal_net_power = matrix_best[0, 2]  # 最优净功率
        
        logger.info(f"优化完成!")
        logger.info(f"最优风机转速: {optimal_fan_speed:.2f} rpm")
        logger.info(f"最优背压: {optimal_backpressure:.3f} kPa")
        logger.info(f"最优净功率: {optimal_net_power:.2f} MW")
        
        return {
            'scenario': load_scenario,
            'base_load': base_load,
            'optimal_fan_speed': optimal_fan_speed,
            'optimal_backpressure': optimal_backpressure,
            'optimal_net_power': optimal_net_power,
            'trace_list': trace_list
        }
        
    except Exception as e:
        logger.error(f"优化过程中出现错误: {str(e)}")
        return None

def run_comprehensive_simulation():
    """运行综合仿真"""
    print("=" * 60)
    print("火电厂冷端优化系统 - 模拟数据运行")
    print("=" * 60)
    
    # 设置日志
    logger = setup_logger()
    
    # 创建数据生成器
    data_generator = MockDataGenerator()
    
    # 创建结果目录
    os.makedirs("simulation_results", exist_ok=True)
    
    # 运行不同负荷场景的优化
    scenarios = ["low", "normal", "high"]
    results = []
    
    for scenario in scenarios:
        print(f"\n正在运行 {scenario} 负荷场景...")
        result = run_single_optimization(data_generator, logger, scenario)
        if result:
            results.append(result)
        
        # 等待一下，避免连续运行太快
        time.sleep(2)
    
    # 生成对比报告
    if results:
        generate_comparison_report(results, logger)
    
    print("\n仿真完成！结果保存在 simulation_results 目录中")

def generate_comparison_report(results, logger):
    """生成对比报告"""
    logger.info("生成对比报告...")
    
    # 创建对比图表
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 12))
    
    scenarios = [r['scenario'] for r in results]
    loads = [r['base_load'] for r in results]
    fan_speeds = [r['optimal_fan_speed'] for r in results]
    backpressures = [r['optimal_backpressure'] for r in results]
    net_powers = [r['optimal_net_power'] for r in results]
    
    # 负荷-净功率关系
    ax1.plot(loads, net_powers, 'o-', linewidth=2, markersize=8)
    ax1.set_xlabel('机组负荷 (MW)')
    ax1.set_ylabel('最优净功率 (MW)')
    ax1.set_title('负荷-净功率关系')
    ax1.grid(True, alpha=0.3)
    
    # 负荷-背压关系
    ax2.plot(loads, backpressures, 's-', linewidth=2, markersize=8, color='orange')
    ax2.set_xlabel('机组负荷 (MW)')
    ax2.set_ylabel('最优背压 (kPa)')
    ax2.set_title('负荷-背压关系')
    ax2.grid(True, alpha=0.3)
    
    # 负荷-风机转速关系
    ax3.plot(loads, fan_speeds, '^-', linewidth=2, markersize=8, color='green')
    ax3.set_xlabel('机组负荷 (MW)')
    ax3.set_ylabel('最优风机转速 (rpm)')
    ax3.set_title('负荷-风机转速关系')
    ax3.grid(True, alpha=0.3)
    
    # 背压-净功率关系
    ax4.plot(backpressures, net_powers, 'd-', linewidth=2, markersize=8, color='red')
    ax4.set_xlabel('背压 (kPa)')
    ax4.set_ylabel('净功率 (MW)')
    ax4.set_title('背压-净功率关系')
    ax4.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig("simulation_results/optimization_comparison.png", dpi=300, bbox_inches='tight')
    plt.close()
    
    # 生成文本报告
    with open("simulation_results/optimization_report.txt", "w", encoding="utf-8") as f:
        f.write("火电厂冷端优化系统 - 仿真结果报告\n")
        f.write("=" * 50 + "\n\n")
        
        for result in results:
            f.write(f"场景: {result['scenario']}\n")
            f.write(f"基础负荷: {result['base_load']:.1f} MW\n")
            f.write(f"最优风机转速: {result['optimal_fan_speed']:.2f} rpm\n")
            f.write(f"最优背压: {result['optimal_backpressure']:.3f} kPa\n")
            f.write(f"最优净功率: {result['optimal_net_power']:.2f} MW\n")
            f.write("-" * 30 + "\n")
    
    logger.info("对比报告已生成")

def run_quick_test():
    """快速测试函数"""
    print("运行快速测试...")
    
    logger = setup_logger()
    data_generator = MockDataGenerator()
    
    # 只运行一个正常负荷场景
    result = run_single_optimization(data_generator, logger, "normal")
    
    if result:
        print(f"\n测试结果:")
        print(f"最优风机转速: {result['optimal_fan_speed']:.2f} rpm")
        print(f"最优背压: {result['optimal_backpressure']:.3f} kPa")
        print(f"最优净功率: {result['optimal_net_power']:.2f} MW")
    else:
        print("测试失败")

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == "test":
        # 快速测试模式
        run_quick_test()
    else:
        # 完整仿真模式
        run_comprehensive_simulation() 